/*
 * Copyright (c) 2006, 2007 FTS Team
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the FTS Team nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *      FTS.hpp
 *
 * $FTS$
 */
#ifndef _FTS_HPP__
#define _FTS_HPP__ 1

/**
  @file FTS.hpp
  @brief Base definitions for full-text search system
*/

#include <FTSTypes.h>

namespace FTSS // FullTextSearchSystem
{

#define WE_ZONE_LENGTH      7
#define WE_WORDFORM_LENGTH  5
#define WE_DOCPOS_LENGTH    20

/**
  @struct WordEntry FTS.hpp <FTS.hpp>
  @brief Word entry
*/
struct WordEntry
{
	/**
	 @brief Data
	 <pre>
	 12345678 12345678 12345678 12345678
	                             ZZZZZZZ - Zone, first 7 bits
	                       YYYY Y        - Word Form, second 5 bits
	 XXXX XXXXXXXX XXXXXXXX              - Position in Document, last 20 bits

	 </pre>
	*/
	WordEntry_t       data;

	/**
	  @brief Constructor
	  @param iPosition - Position in Document
	  @param iWordForm - Word Form ID
	  @param iZoneId - Document Zone ID
	*/
	inline WordEntry(const DocumentPos_t & iPosition = 0, const WordForm_t & iWordForm = 0, const ZoneId_t & iZoneId = 0) throw()
	{
		data =((iPosition & 0x000FFFFF) << 12) +
		      ((iWordForm & 0x0000001F) <<  7) +
		       (iZoneId   & 0x0000007F);
	}

	/**
	  @brief Copy Constructor
	  @param oEntry - WordEntry object
	*/
	inline WordEntry(const WordEntry & oEntry) throw(): data(oEntry.data) { ;; }

	/**
	  @brief Operator =
	  @param oEntry word entry
	  @return reference to self
	*/
	inline WordEntry & operator=(const WordEntry & oEntry) throw() { data = oEntry.data; return *this; }

	/** Get Word Position */
	inline WordEntry_t GetPosition() const throw() { return ((data >> 12) & 0x000FFFFF); }
	/** Get Form ID */
	inline WordEntry_t GetForm()     const throw() { return ((data >>  7) & 0x0000001F); }
	/** Get Document Zone ID */
	inline WordEntry_t GetZone()     const throw() { return ((data)       & 0x0000007F); }

	/**
	  @brief Adjust form of word
	  @param iWordForm - word hash
	  @return Form of word
	*/
	inline static WordEntry_t AdjustForm(const WordForm_t & iWordForm) throw() { return (iWordForm & 0x0000001F); }

	/**
	  @brief Set document position
	  @param iPosition - document position
	*/
	inline void SetPosition(const DocumentPos_t & iPosition = 0) throw() { data |= ((iPosition & 0x000FFFFF) << 12); }

	/**
	  @brief Set form
	  @param iWordForm - word hash
	*/
	inline void SetForm(const WordForm_t & iWordForm = 0)        throw() { data |= ((iWordForm & 0x0000001F) <<  7); }

	/**
	  @brief Set zone
	  @param iZoneId - word zone
	*/
	inline void SetZone(const ZoneId_t & iZoneId = 0)            throw() { data |= (iZoneId   & 0x0000007F); }
};

/**
  @struct DocumentEntry FTS.hpp <FTS.hpp>
  @brief Document entry
*/
struct DocumentEntry
{
	/** Document Id                   */
	DocumentId_t    doc_id;
	/** offset of next document entry */
	Offset_t        size;
	/** Array od word entries         */
	WordEntry       words[1];
	/**
	  @brief Get term frequency
	  @return document term frequency
	*/
	inline Size_t tf() const throw() { return (size - sizeof(Offset_t) - sizeof(doc_id)) / sizeof(WordEntry); }
};

} // namespace FTSS
#endif // _FTS_HPP__
// End.
